home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mac Magazin/MacEasy 2
/
Mac Magazin and MacEasy Magazine CD - Issue 02.iso
/
Sharewarebibliothek
/
PowerMac
/
Rotate PPC ƒ
/
RotatePPC.c
< prev
next >
Wrap
Text File
|
1994-07-11
|
16KB
|
655 lines
/* This program reads a set of 3D points from a file and
then displays them in a window where they can be rotated
around left-right and up-down.
This version is only for the Power Macintosh.
It assumes System 7.1.2.
It gives examples of using the required apple events,
file dropping, and reading c-style from an FSS record.
The rotation code is from the NewSpaceShuttle source.
This code and program, as far as they are able to be,
are in the public domain.
Craig Kloeden <craig@raru.adelaide.edu.au>
9 June 1994
*/
#include <QDOffscreen.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <EPPC.h>
#include <AppleEvents.h>
#define MaxPoints 2500
#define PI 3.141592653589793
#define PI2 6.283185307179586
void main (void);
void init (void);
void HandleEvent (void);
void HandleMouseDown (EventRecord *theEvent);
void HandleMenu (long mSelect);
void finishup (void);
void mousepress (Point p);
void rotate (void);
void getuserfile (void);
void readfile (short refnum, long parid, Str63 name);
void installAEhandlers (void);
void DoHighLevelEvent (EventRecord *theEvent);
pascal OSErr openAE (AppleEvent *theEvent, AppleEvent *reply, long refcon);
pascal OSErr quitAE (AppleEvent *theEvent, AppleEvent *reply, long refcon);
pascal OSErr printAE (AppleEvent *theEvent, AppleEvent *reply, long refcon);
pascal OSErr startAE (AppleEvent *theEvent, AppleEvent *reply, long refcon);
void died (char desc[255], int code, int ref);
double Xangle, Yangle, Zangle;
double aaa[MaxPoints][3];
int cc[MaxPoints];
int N;
double DD = 120;
Boolean done;
Rect frameRect, dragRect;
CWindowPtr thewindow;
GWorldPtr drawWorldP;
PixMapHandle thePixMapH, windowPixMapH;
PixMapPtr drawPixMapP, windowPixMapP;
MenuHandle applemenu, filemenu, editmenu, optionmenu;
GWorldPtr saveWorld;
GDHandle saveDevice;
OSErr err;
RGBColor black = {0,0,0}, white = {65535, 65535, 65535};
RGBColor red = {65535, 0, 0}, green = {0, 65535, 0}, blue = {0, 0, 65535};
//************************************************************************
void main (void)
{
init ();
done = false;
while (! done)
{
HandleEvent();
}
finishup ();
}
//************************************************************************
void init (void)
{
EventRecord tempEvent;
/* Initialize Managers */
InitGraf (&qd.thePort);
InitFonts ();
FlushEvents(everyEvent - osMask - diskMask, 0);
InitWindows ();
InitMenus ();
TEInit ();
InitDialogs (nil);
InitCursor ();
MaxApplZone();
MoreMasters();
EventAvail(everyEvent, &tempEvent);
EventAvail(everyEvent, &tempEvent);
EventAvail(everyEvent, &tempEvent);
/* set up menus */
applemenu = GetMenu(128);
if (applemenu == NULL) died ("Can't find Apple Menu Resource", 0, 001);
AddResMenu(applemenu, 'DRVR');
filemenu = GetMenu(129);
editmenu = GetMenu(130);
optionmenu = GetMenu(131);
InsertMenu(applemenu, 0);
InsertMenu(filemenu, 0);
InsertMenu(editmenu, 0);
InsertMenu(optionmenu, 0);
DrawMenuBar();
dragRect = qd.screenBits.bounds;
SetRect (&frameRect, 0, 0, 400, 400);
/* because this is PPC only we dont have to check for old
systems or the GWorld stuff :-)
*/
/* set up the main window */
thewindow = (CWindowPtr) GetNewCWindow (400, nil, (WindowPtr)-1L);
if (thewindow == NULL) died ("Can't get Window Resource", 0, 002);
SetPort ((WindowPtr)thewindow);
GetGWorld(&saveWorld, &saveDevice);
windowPixMapH = GetGWorldPixMap(saveWorld);
HLockHi((Handle)windowPixMapH);
LockPixels(windowPixMapH);
windowPixMapP = *thewindow->portPixMap;
/* set up offscreen GWorld */
err = NewGWorld(&drawWorldP, 8, &frameRect, nil, nil, 0);
if (err) died ("Could not Create GWorld", err, 003);
thePixMapH = GetGWorldPixMap(drawWorldP);
HLockHi((Handle)thePixMapH);
LockPixels(thePixMapH);
drawPixMapP = *thePixMapH;
/* clear the GWorld */
SetGWorld(drawWorldP, nil);
PaintRect(&frameRect);
SetGWorld(saveWorld, saveDevice);
/* no points yet */
N = 0;
installAEhandlers ();
}
//************************************************************************
void HandleEvent(void)
{
EventRecord theEvent;
HiliteMenu(0);
if (WaitNextEvent (everyEvent, &theEvent, 40, NULL))
switch (theEvent.what)
{
case mouseDown:
HandleMouseDown(&theEvent);
break;
case keyDown:
if ((theEvent.modifiers & cmdKey) != 0)
{
HandleMenu(MenuKey((char) (theEvent.message & charCodeMask)));
}
break;
case updateEvt:
BeginUpdate((WindowPtr)thewindow);
/* copy GWorld to screen window */
SetGWorld(saveWorld, saveDevice);
CopyBits((BitMapPtr)drawPixMapP, (BitMapPtr)windowPixMapP,
&frameRect, &frameRect, srcCopy, nil);
EndUpdate((WindowPtr)thewindow);
break;
case activateEvt:
InvalRect(&thewindow->portRect);
break;
case osEvt:
if (theEvent.message & 1) /* Resume Event */
{
InitCursor();
}
else /* Suspend Event */
{
InitCursor();
}
break;
case kHighLevelEvent:
DoHighLevelEvent (&theEvent);
break;
}
}
//************************************************************************
void HandleMouseDown (EventRecord *theEvent)
{
WindowPtr awindow;
int windowCode = FindWindow (theEvent->where, &awindow);
switch (windowCode)
{
case inSysWindow:
SystemClick (theEvent, awindow);
break;
case inMenuBar:
HandleMenu(MenuSelect(theEvent->where));
break;
case inDrag:
if (awindow == (WindowPtr)thewindow)
DragWindow((WindowPtr)thewindow, theEvent->where, &dragRect);
break;
case inContent:
if (awindow == (WindowPtr)thewindow)
{
if (awindow != FrontWindow())
SelectWindow((WindowPtr)thewindow);
else
{
GlobalToLocal(&theEvent->where);
mousepress (theEvent->where);
}
}
break;
case inGoAway:
if (awindow == (WindowPtr)thewindow &&
TrackGoAway((WindowPtr)thewindow, theEvent->where))
{
HideWindow ((WindowPtr)thewindow);
N = 0;
}
break;
}
}
//************************************************************************
void HandleMenu (long mSelect)
{
int menuID = HiWord(mSelect);
int menuItem = LoWord(mSelect);
Str255 name;
GrafPtr savePort;
unsigned long ticks;
switch (menuID)
{
case 128: /* apple menu */
if (menuItem == 1) /* About */
{
Alert(128,NULL);
break;
}
/* system apple menu item */
GetPort(&savePort);
GetItem(applemenu, menuItem, name);
OpenDeskAcc(name);
SetPort(savePort);
break;
case 129: /* file menu */
switch (menuItem)
{
case 1: /* open */
getuserfile();
break;
case 3: /* quit */
done = true;
break;
}
break;
case 131: /* option menu */
switch (menuItem)
{
case 1: /* perspective */
if (DD == 120)
{
CheckItem (optionmenu, 1, FALSE);
DD = 100000;
}
else
{
CheckItem (optionmenu, 1, TRUE);
DD = 120;
}
SetGWorld(drawWorldP, nil);
PaintRect(&frameRect);
rotate ();
SetGWorld(saveWorld, saveDevice);
CopyBits((BitMapPtr)drawPixMapP, (BitMapPtr)windowPixMapP,
&frameRect, &frameRect, srcCopy, nil);
break;
case 3: /* rotate slow*/
while (! Button())
{
ticks = TickCount();
Yangle++;
SetGWorld(drawWorldP, nil);
PaintRect(&frameRect);
rotate ();
SetGWorld(saveWorld, saveDevice);
while (TickCount() < ticks + 1) {}
CopyBits((BitMapPtr)drawPixMapP, (BitMapPtr)windowPixMapP,
&frameRect, &frameRect, srcCopy, nil);
}
break;
case 4: /* rotate fast*/
while (! Button())
{
ticks = TickCount();
Yangle += 2;
SetGWorld(drawWorldP, nil);
PaintRect(&frameRect);
rotate ();
SetGWorld(saveWorld, saveDevice);
while (TickCount() < ticks + 1) {}
CopyBits((BitMapPtr)drawPixMapP, (BitMapPtr)windowPixMapP,
&frameRect, &frameRect, srcCopy, nil);
}
break;
}
break;
}
}
//************************************************************************
void finishup (void) /* get outa here */
{
ExitToShell();
}
//************************************************************************
void mousepress (Point p)
{
Point p1;
int x, y, x1, y1;
double sx, sy, sz;
/* save original rotation angles */
sx = Xangle;
sy = Yangle;
sz = Zangle;
x1 = 0;
y1 = 0;
while (StillDown()) /* loop while button held down */
{
GetMouse (&p1);
x = p.v - p1.v;
y = p.h - p1.h;
if (x != x1 || y != y1) /* if mouse moved since last time around */
{
Xangle = sx - x;
Yangle = sy + y;
SetGWorld(drawWorldP, nil);
PaintRect(&frameRect);
rotate ();
SetGWorld(saveWorld, saveDevice);
CopyBits((BitMapPtr)drawPixMapP, (BitMapPtr)windowPixMapP,
&frameRect, &frameRect, srcCopy, nil);
x1 = x;
y1 = y;
}
}
}
//************************************************************************
void rotate ()
{
int Ec;
double XV, YV, ZV, X, Y, Z, X3, Y3, Z3;
double CB, SB, CH, SH, CP, SP;
double AM, BM, CM, DM, EM, FM, GM, HM, IM;
int XX, YY;
double P, B, H;
P = PI2 * Xangle / 360 - PI;
B = PI2 * Zangle / 360;
H = PI2 * Yangle / 360;
CB = cos(B);
SB = sin(B);
CH = cos(H);
SH = sin(H);
CP = cos(P);
SP = sin(P);
AM = CB * CH - SH * SP * SB;
BM = -CB * SH - SP * CH * SB;
CM = CP * SB;
DM = SH * CP;
EM = CP * CH;
FM = SP;
GM = -CH * SB - SH * SP * CB;
HM = SH * SB - SP * CH * CB;
IM = CP * CB;
XV = - DD * CP * SH;
YV = - DD * CP * CH;
ZV = - DD * SP;
for (Ec = 0; Ec < N; Ec++)
{
X = aaa[Ec][0] - XV;
Y = aaa[Ec][1] - YV;
Z = aaa[Ec][2] - ZV;
X3 = AM * X + BM * Y + CM * Z;
Y3 = DM * X + EM * Y + FM * Z;
Z3 = GM * X + HM * Y + IM * Z;
XX = round (10 * DD * X3 / Y3 + 200);
YY = round (10 * DD * Z3 / Y3 + 200);
if (cc[Ec] != 0)
{
/* draw a line */
RGBForeColor (&white);
if (abs(cc[Ec]) == 1) RGBForeColor (&red);
if (abs(cc[Ec]) == 2) RGBForeColor (&green);
if (abs(cc[Ec]) == 3) RGBForeColor (&blue);
if (cc[Ec] < 0) MoveTo (XX, YY); /* draw a point */
LineTo (XX, YY);
}
else
/* move to starting point of line */
MoveTo (XX, YY);
}
RGBForeColor (&black);
}
//************************************************************************
void getuserfile (void)
{
SFTypeList types;
StandardFileReply mySFR;
/* get a file name */
types[0] = 'TEXT';
StandardGetFile (NULL, 1, types, &mySFR);
if (mySFR.sfGood)
{
readfile (mySFR.sfFile.vRefNum, mySFR.sfFile.parID,
mySFR.sfFile.name);
}
}
//************************************************************************
void readfile (short refnum, long parid, Str63 name)
{
FILE *points;
int i, j;
double max, maybe;
SetWTitle ((WindowPtr)thewindow, name);
PtoCstr((StringPtr) name);
err = HSetVol (NULL, refnum, parid);
if (err) died ("Could not Set Volume", err, 4);
/* read points from the file */
points = fopen ((char *)name, "r");
if (points == NULL) died ("Can't Open File", 0, 5);
N = 0;
do
{
err = (fscanf(points, "%lf %lf %lf %d", &aaa[N][0], &aaa[N][1],
&aaa[N][2], &cc[N]));
if (err != EOF) N++;
if (err != 4 && err != EOF)
{
fclose (points);
died ("Error Reading File", err, 6);
}
if (N > MaxPoints)
{
fclose (points);
died ("Too Many Lines in File", 0, 7);
}
}
while (err != EOF);
fclose (points);
/* get maximum distance of points from origin */
max = 0;
for (i=0; i<N; i++)
{
maybe = sqrt(aaa[i][0]*aaa[i][0] + aaa[i][1]*aaa[i][1] +
aaa[i][2]*aaa[i][2]);
if (maybe > max) max = maybe;
}
if (max == 0) died ("All Points at Origin", 0, 8);
/* scale the points */
for (i=0; i<N; i++)
for (j=0; j<3; j++)
aaa[i][j] /= max/19;
/* reset rotation angles */
Xangle = 0;
Yangle = 0;
Zangle = 0;
/* draw the picture to GWorld and screen */
SetGWorld(drawWorldP, nil);
PaintRect(&frameRect);
rotate ();
SetGWorld(saveWorld, saveDevice);
ShowWindow ((WindowPtr)thewindow);
}
//************************************************************************
void installAEhandlers (void)
{
/* install the required apple event handlers */
AEEventHandlerUPP OPENae, QUITae, STARTae, PRINTae;
/* must use these for PPC proc pointers */
OPENae = NewAEEventHandlerProc ((ProcPtr) &openAE);
QUITae = NewAEEventHandlerProc ((ProcPtr) &quitAE);
STARTae = NewAEEventHandlerProc ((ProcPtr) &startAE);
PRINTae = NewAEEventHandlerProc ((ProcPtr) &printAE);
err = AEInstallEventHandler (kCoreEventClass, kAEOpenDocuments,
OPENae, 0, FALSE);
if (err) died ("Error Installing OpenDoc Apple Event", err, 9);
err = AEInstallEventHandler (kCoreEventClass, kAEQuitApplication,
QUITae, 0, FALSE);
if (err) died ("Error Installing QuitApp Apple Event", err, 10);
err = AEInstallEventHandler (kCoreEventClass, kAEOpenApplication,
STARTae, 0, FALSE);
if (err) died ("Error Installing OpenApp Apple Event", err, 11);
err = AEInstallEventHandler (kCoreEventClass, kAEPrintDocuments,
PRINTae, 0, FALSE);
if (err) died ("Error Installing PrintDoc Apple Event", err, 12);
}
//************************************************************************
void DoHighLevelEvent (EventRecord *theEvent)
{
/* process high level events */
err = AEProcessAppleEvent (theEvent);
if (err) died ("Error Processing Apple Event", err, 13);
}
//************************************************************************
pascal OSErr openAE (AppleEvent *theEvent, AppleEvent *reply, long refcon)
{
AEDescList docList;
long n;
AEKeyword keywd;
DescType rtype;
FSSpec myFSS;
Size acsize;
/* open document apple event */
err = AEGetParamDesc (theEvent, keyDirectObject, typeAEList, &docList);
if (err) died ("Error Processing Apple Event", err, 14);
/* count number of document to be opened */
err = AECountItems (&docList, &n);
if (err) died ("Error Processing Apple Event", err, 15);
if (n < 1) died ("No File for OpenDoc Apple Event", 0, 16);
/* get FSS record of the first document only */
err = AEGetNthPtr (&docList, 1, typeFSS, &keywd, &rtype,
&myFSS, sizeof(myFSS), &acsize);
if (err) died ("Error Processing Apple Event", err, 17);
/* get rid of storage */
err = AEDisposeDesc (&docList);
if (err) died ("Error Processing Apple Event", err, 18);
/* open the passed file */
readfile (myFSS.vRefNum, myFSS.parID, myFSS.name);
return noErr;
}
//************************************************************************
pascal OSErr quitAE(AppleEvent *theEvent, AppleEvent *reply, long refcon)
{
/* quit apple event - set the done flag */
done = true;
return noErr;
}
//************************************************************************
pascal OSErr printAE (AppleEvent *theEvent, AppleEvent *reply, long refcon)
{
/* print apple event not handled here */
return errAEEventNotHandled;
}
//************************************************************************
pascal OSErr startAE (AppleEvent *theEvent, AppleEvent *reply, long refcon)
{
/* startup apple event - ask for an input file */
getuserfile();
return noErr;
}
//************************************************************************
void died (char desc[255], int code, int ref)
{
/* nasty error has occurred - report it and quit */
int go;
char a[50], b[50];
CtoPstr (desc);
NumToString (code, (StringPtr)a);
NumToString (ref, (StringPtr)b);
ParamText ((StringPtr)desc, (StringPtr)a, (StringPtr)b, NULL);
go = Alert(129,NULL);
ExitToShell();
}
//************************************************************************